package plp.funcoo.expressions;

import plp.funcoo.environment.compilation.CompilationEnvironment;
import plp.funcoo.environment.compilation.Environment;
import plp.funcoo.environment.execution.ExecutionContext;
import plp.funcoo.environment.execution.ExecutionEnvironment;
import plp.funcoo.exceptions.ClassAlreadyDeclared;
import plp.funcoo.exceptions.ClassNotDeclared;
import plp.funcoo.exceptions.MethodAlreadDeclared;
import plp.funcoo.exceptions.MethodNotDeclared;
import plp.funcoo.exceptions.VarAlreadyDeclared;
import plp.funcoo.exceptions.VarNotDeclared;
import plp.funcoo.types.PrimitiveType;
import plp.funcoo.util.Type;
import plp.funcoo.value.IntegerValue;


/**
* Um objeto desta classe representa uma Expressao de mais unario.
*/
public class ExpPlus extends UnaryExpression{

	/**
	 * Constroi uma Expressao de mais unario com expressao especificada
	 *
	 * @param exp Expressao cuja avaliacao resulta <code>ValorInteiro</code>.
	 */
	public ExpPlus(Expression exp){
		super(exp, "+");
	}
	/**
	 * Retorna o valor da Expressao de mais unario
	 */
	@Override
	public ExecutionEnvironment evaluate(ExecutionEnvironment envi) throws VarNotDeclared, MethodNotDeclared, VarAlreadyDeclared, MethodAlreadDeclared {
		envi = getExp().evaluate(envi); 
		IntegerValue exp = (IntegerValue) ((ExecutionContext) envi).getValueAnalyzed();
		((ExecutionContext) envi).setValueAnalyzed(new IntegerValue( + exp.getValue() ));
		return envi;
	}

	@Override
	public boolean typeCheck(CompilationEnvironment envi)
			throws VarAlreadyDeclared, VarNotDeclared, ClassAlreadyDeclared,
			ClassNotDeclared {
		return getExp().getType(envi).isInteger() || getExp().getType(envi).isFloat();
	}

	@Override
	public Type getType(Environment envi) throws VarNotDeclared,
			ClassNotDeclared {
		return PrimitiveType.Type_INT;
	}

	public Expression makeCopy() {
		return new ExpPlus(this.getExp().makeCopy());
	}
}
